module ffd(D, clk, reset, we, Q);
    parameter n = 1;
    input [n-1:0] D;
    input clk, reset, we;
    output [n-1:0] Q;
    reg [n-1:0] Q;
 
    always @(posedge clk)
    begin
        if(reset) begin Q = 0; end
        else if (we) begin Q <= D; end
    end
endmodule

module ffda(D, clk, reset, we, Q);
    parameter n = 1;
    input [n-1:0] D;
    input clk, reset, we;
    output [n-1:0] Q;
    reg [n-1:0] Q;
 
    always @(posedge clk or posedge reset)
    begin
        if(reset) begin Q = 0; end
        else if (we) begin Q <= D; end
    end
endmodule


module latch(D, clk, reset, we, Q);
    parameter n = 1;
    input [n-1:0] D;
    input clk, reset, we;
    output [n-1:0] Q;
    reg [n-1:0] Q;
 
    always @(*)
    begin
        if(reset) begin Q = 0; end
        else if (we) begin Q <= D; end
    end
endmodule

module mux2 #(parameter WIDTH = 16)
             (input  [WIDTH-1:0] d0, d1, 
              input              s, 
              output [WIDTH-1:0] y);

  assign #1 y = s ? d1 : d0; 
endmodule

module mux3 #(parameter WIDTH = 16)
             (input  [WIDTH-1:0] d0, d1, d2,
              input  [1:0]       s, 
              output [WIDTH-1:0] y);

  assign #1 y = s[1] ? d2 : (s[0] ? d1 : d0); 
endmodule

module mux4 #(parameter WIDTH = 16)
             (input  [WIDTH-1:0] d0, d1, d2, d3,
              input  [1:0]       s, 
              output [WIDTH-1:0] y);

  assign #1 y = s[1] ? (s[0] ? d3 : d2)
                     : (s[0] ? d1 : d0); 
endmodule